/*
 * Copyright (c) 2020-2099 the original author or authors. All rights reserve.
 */
package org.tianyun.cloud.web.controller;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.tianyun.cloud.web.logger.LogPrinter;
import org.tianyun.cloud.web.logger.annotation.EnableLogPrint;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * 请求拦截器
 *
 * @auther ebert_chan
 */
@Aspect
public class HttpRequestAspect {

    /**
     * LOGGER
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(HttpRequestAspect.class);

    /**
     * 请求日志处理
     */
    private LogPrinter logPrinter;

    /**
     * 构造方法
     *
     * @param logPrinter
     */
    public HttpRequestAspect(LogPrinter logPrinter) {
        this.logPrinter = logPrinter;
    }

    @Around("(@within(org.springframework.web.bind.annotation.RestController) || @within(org.springframework.stereotype.Controller)) && (@annotation(org.springframework.web.bind.annotation.RequestMapping) || @annotation(org.springframework.web.bind.annotation.GetMapping) || @annotation(org.springframework.web.bind.annotation.PostMapping) || @annotation(org.springframework.web.bind.annotation.DeleteMapping) || @annotation(org.springframework.web.bind.annotation.PutMapping) || @annotation(org.springframework.web.bind.annotation.PatchMapping))")
    public Object execute(ProceedingJoinPoint pjp) throws Throwable {
        HttpServletRequest request = null;
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            return pjp.proceed();
        }
        if (!LOGGER.isInfoEnabled()) {
            return pjp.proceed();
        }
        request = ((ServletRequestAttributes) requestAttributes).getRequest();

        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        Method method = methodSignature.getMethod();
        EnableLogPrint enableLogPrint = method.getAnnotation(EnableLogPrint.class);

        if (enableLogPrint == null || enableLogPrint.in()) {
            // 打印请求信息
            logPrinter.writeRequestInformation(request);
            // 打印入参信息
            logPrinter.writeMethodInParameters(pjp.getArgs());
        }

        // 调用拦截方法
        Object result = pjp.proceed();

        if (enableLogPrint == null || enableLogPrint.out()) {
            // 打印出参信息
            logPrinter.writeMethodOutParameters(result);
        }

        return result;
    }

}
